﻿using UnityEngine;
using System;
using System.Collections;

namespace Hont.UMotionGraph
{
    public abstract class MoGraphEffector : MonoBehaviour, IMoGraphEffector
    {
        [Serializable]
        public class FallOffSetting
        {
            public bool Toggle;
            public string Sharp;
            public Vector3 Offset;
            public float Size = 1f;
            public float FallOffValue = 0.5f;
        }

        public FallOffSetting fallOffSetting;
        protected IMoGraphContainer mMoGraphContainer;
        protected bool mIsInited;


        public virtual void Init(IMoGraphContainer container)
        {
            this.mMoGraphContainer = container;
            mIsInited = true;
        }

        protected virtual void Update() { }

        public virtual float CalcFallOffProportion(int inx)
        {
            float result = 1f;
            if (!fallOffSetting.Toggle) return result;

            var sphere = new Sphere(transform.position + fallOffSetting.Offset, fallOffSetting.Size * fallOffSetting.FallOffValue);
            var outlineSphere = new Sphere(transform.position + fallOffSetting.Offset, fallOffSetting.Size);

            var tmpValue = mMoGraphContainer.GetValue(0, inx);

            if (!sphere.Contain(tmpValue) && outlineSphere.Contain(tmpValue))
            {
                var directionLength = tmpValue - (transform.position + fallOffSetting.Offset);
                var direction = directionLength.normalized;
                var maxValueMag = (outlineSphere.Radius * direction).sqrMagnitude;
                var minValueMag = (sphere.Radius * direction).sqrMagnitude;
                var curValueMag = directionLength.sqrMagnitude - minValueMag;
                result = curValueMag / Math.Abs(maxValueMag - minValueMag);
                result = 1 - result;
            }
            else if (!sphere.Contain(tmpValue))
            {
                result = 0;
            }

            return result;
        }

        public Vector3 Execute(int inx, Vector3 inValue)
        {
            if (!mIsInited) return inValue;

            var proportion = CalcFallOffProportion(inx);
            return Execute(inx, inValue, proportion);
        }

        public abstract Vector3 Execute(int inx, Vector3 inValue, float fallOffProportion);

        protected virtual void OnDrawGizmos()
        {
            if (fallOffSetting == null) return;
            if (!fallOffSetting.Toggle) return;

            var sphere = new Sphere(transform.position + fallOffSetting.Offset, fallOffSetting.Size * fallOffSetting.FallOffValue);
            var outlineSphere = new Sphere(transform.position + fallOffSetting.Offset, fallOffSetting.Size);

            var oldColor = Gizmos.color;

            Gizmos.color = Color.yellow;
            Gizmos.DrawWireSphere(sphere.Center, sphere.Radius);

            Gizmos.color = Color.red;
            Gizmos.DrawWireSphere(outlineSphere.Center, outlineSphere.Radius);

            Gizmos.color = oldColor;
        }
    }
}
